--- gcc/config/avr/avr.c.orig	2008-06-08 10:24:28.171355800 -0600
+++ gcc/config/avr/avr.c	2008-06-08 10:29:42.276013800 -0600
@@ -51,6 +51,7 @@
 static int avr_naked_function_p (tree);
 static int interrupt_function_p (tree);
 static int signal_function_p (tree);
+static int nmi_function_p (tree);
 static int avr_OS_task_function_p (tree);
 static int avr_regs_to_save (HARD_REG_SET *);
 static int sequent_regs_live (void);
@@ -118,17 +119,24 @@ int avr_asm_only_p = 0;
 int avr_have_movw_lpmx_p = 0;
 
 static const struct base_arch_s avr_arch_types[] = {
-  { 1, 0, 0, 0, 0, 0, 0, 0, NULL },  /* unknown device specified */
-  { 1, 0, 0, 0, 0, 0, 0, 0, "__AVR_ARCH__=1"   },
-  { 0, 0, 0, 0, 0, 0, 0, 0, "__AVR_ARCH__=2"   },
-  { 0, 0, 0, 1, 0, 0, 0, 0, "__AVR_ARCH__=25"  },
-  { 0, 0, 1, 0, 0, 0, 0, 0, "__AVR_ARCH__=3"   },
-  { 0, 0, 1, 0, 1, 0, 0, 0, "__AVR_ARCH__=31"  },
-  { 0, 0, 1, 1, 0, 0, 0, 0, "__AVR_ARCH__=35"  },
-  { 0, 1, 0, 1, 0, 0, 0, 0, "__AVR_ARCH__=4"   },
-  { 0, 1, 1, 1, 0, 0, 0, 0, "__AVR_ARCH__=5"   },
-  { 0, 1, 1, 1, 1, 1, 0, 0, "__AVR_ARCH__=51"  },
-  { 0, 1, 1, 1, 1, 1, 1, 0, "__AVR_ARCH__=6"   }
+  { 1, 0, 0, 0, 0, 0, 0, 0, 0, NULL },  /* Unknown device specified.  */
+  { 1, 0, 0, 0, 0, 0, 0, 0, 0, "__AVR_ARCH__=1"   },
+  { 0, 0, 0, 0, 0, 0, 0, 0, 0, "__AVR_ARCH__=2"   },
+  { 0, 0, 0, 1, 0, 0, 0, 0, 0, "__AVR_ARCH__=25"  },
+  { 0, 0, 1, 0, 0, 0, 0, 0, 0, "__AVR_ARCH__=3"   },
+  { 0, 0, 1, 0, 1, 0, 0, 0, 0, "__AVR_ARCH__=31"  },
+  { 0, 0, 1, 1, 0, 0, 0, 0, 0, "__AVR_ARCH__=35"  },
+  { 0, 1, 0, 1, 0, 0, 0, 0, 0, "__AVR_ARCH__=4"   },
+  { 0, 1, 1, 1, 0, 0, 0, 0, 0, "__AVR_ARCH__=5"   },
+  { 0, 1, 1, 1, 1, 1, 0, 0, 0, "__AVR_ARCH__=51"  },
+  { 0, 1, 1, 1, 1, 1, 1, 0, 0, "__AVR_ARCH__=6"   },
+  { 0, 1, 0, 1, 0, 0, 0, 1, 0, "__AVR_ARCH__=101" },
+  { 0, 1, 1, 1, 0, 0, 0, 1, 0, "__AVR_ARCH__=102" },
+  { 0, 1, 1, 1, 0, 0, 0, 1, 1, "__AVR_ARCH__=103" },
+  { 0, 1, 1, 1, 1, 1, 0, 1, 0, "__AVR_ARCH__=104" },
+  { 0, 1, 1, 1, 1, 1, 0, 1, 1, "__AVR_ARCH__=105" },
+  { 0, 1, 1, 1, 1, 1, 1, 1, 0, "__AVR_ARCH__=106" },  
+  { 0, 1, 1, 1, 1, 1, 1, 1, 1, "__AVR_ARCH__=107" }
 };
 
 /* These names are used as the index into the avr_arch_types[] table 
@@ -146,7 +154,14 @@ enum avr_arch
   ARCH_AVR4,
   ARCH_AVR5,
   ARCH_AVR51,
-  ARCH_AVR6
+  ARCH_AVR6,
+  ARCH_AVRXMEGA1,
+  ARCH_AVRXMEGA2,
+  ARCH_AVRXMEGA3,
+  ARCH_AVRXMEGA4,
+  ARCH_AVRXMEGA5,
+  ARCH_AVRXMEGA6,
+  ARCH_AVRXMEGA7
 };
 
 struct mcu_type_s {
@@ -279,6 +294,18 @@ static const struct mcu_type_s avr_mcu_t
   { "avr6",         ARCH_AVR6, NULL },
   { "atmega2560",   ARCH_AVR6, "__AVR_ATmega2560__" },
   { "atmega2561",   ARCH_AVR6, "__AVR_ATmega2561__" },
+    /* Enhanced, == 256K.  */
+    /* Xmega, <= 8K FLASH.  */
+    /* Xmega, > 8K, <= 64K FLASH, <= 64K RAM.  */
+    /* Xmega, > 8K, <= 64K FLASH, > 64K RAM.  */
+    /* Xmega, > 64K, <= 128K FLASH, <= 64K RAM.  */
+    /* Xmega, > 64K, <= 128K FLASH, > 64K RAM.  */
+  { "avrxmega5",    ARCH_AVRXMEGA5, NULL },
+  { "atxmega64a1",  ARCH_AVRXMEGA5, "__AVR_ATxmega64A1__" },
+    /* Xmega, > 128K, <= 256K FLASH, <= 64K RAM.  */
+    /* Xmega, > 128K, <= 256K FLASH, > 64K RAM.  */
+  { "avrxmega7",    ARCH_AVRXMEGA7, NULL },
+  { "atxmega128a1", ARCH_AVRXMEGA7, "__AVR_ATxmega128A1__" },
     /* Assembler only.  */
   { "avr1",         ARCH_AVR1, NULL },
   { "at90s1200",    ARCH_AVR1, "__AVR_AT90S1200__" },
@@ -452,6 +479,21 @@ signal_function_p (tree func)
   return a != NULL_TREE;
 }
 
+/* Return nonzero if FUNC is a nmi function as specified
+   by the "nmi" attribute.  */
+
+static int
+nmi_function_p (tree func)
+{
+  tree a;
+
+  if (TREE_CODE (func) != FUNCTION_DECL)
+    return 0;
+
+  a = lookup_attribute ("nmi", DECL_ATTRIBUTES (func));
+  return a != NULL_TREE;
+}
+
 /* Return nonzero if FUNC is a OS_task function.  */
 
 static int
@@ -611,6 +653,7 @@ expand_prologue (void)
   cfun->machine->is_naked = avr_naked_function_p (current_function_decl);
   cfun->machine->is_interrupt = interrupt_function_p (current_function_decl);
   cfun->machine->is_signal = signal_function_p (current_function_decl);
+  cfun->machine->is_nmi = nmi_function_p (current_function_decl);
   cfun->machine->is_OS_task = avr_OS_task_function_p (current_function_decl);
   
   /* Prologue: naked.  */
@@ -646,7 +689,7 @@ expand_prologue (void)
 
       /* Push SREG.  */
       insn = emit_move_insn (tmp_reg_rtx, 
-                             gen_rtx_MEM (QImode, GEN_INT (SREG_ADDR)));
+                             gen_rtx_MEM (QImode, GEN_INT (AVR_SREG_ADDR)));
       RTX_FRAME_RELATED_P (insn) = 1;
       insn = emit_move_insn (pushbyte, tmp_reg_rtx);
       RTX_FRAME_RELATED_P (insn) = 1;
@@ -656,7 +699,7 @@ expand_prologue (void)
          && (TEST_HARD_REG_BIT (set, REG_Z) && TEST_HARD_REG_BIT (set, REG_Z + 1)))
         {
           insn = emit_move_insn (tmp_reg_rtx, 
-                                 gen_rtx_MEM (QImode, GEN_INT (RAMPZ_ADDR)));
+                                 gen_rtx_MEM (QImode, GEN_INT (AVR_RAMPZ_ADDR)));
           RTX_FRAME_RELATED_P (insn) = 1;
           insn = emit_move_insn (pushbyte, tmp_reg_rtx);
           RTX_FRAME_RELATED_P (insn) = 1;
@@ -929,14 +972,14 @@ expand_epilogue (void)
              && (TEST_HARD_REG_BIT (set, REG_Z) && TEST_HARD_REG_BIT (set, REG_Z + 1)))
             {
 	      emit_insn (gen_popqi (tmp_reg_rtx));
-	      emit_move_insn (gen_rtx_MEM(QImode, GEN_INT(RAMPZ_ADDR)), 
+	      emit_move_insn (gen_rtx_MEM(QImode, GEN_INT(AVR_RAMPZ_ADDR)), 
 			      tmp_reg_rtx);
 	    }
 
           /* Restore SREG using tmp reg as scratch.  */
           emit_insn (gen_popqi (tmp_reg_rtx));
       
-          emit_move_insn (gen_rtx_MEM(QImode, GEN_INT(SREG_ADDR)), 
+          emit_move_insn (gen_rtx_MEM(QImode, GEN_INT(AVR_SREG_ADDR)), 
 			  tmp_reg_rtx);
 
           /* Restore tmp REG.  */
@@ -1705,8 +1748,9 @@ output_movhi (rtx insn, rtx operands[], 
 		}
               /*  Use simple load of stack pointer if no interrupts are used
               or inside main or signal function prologue where they disabled.  */
-	      else if (TARGET_NO_INTERRUPTS 
-                        || (reload_completed 
+	      else if (TARGET_NO_INTERRUPTS
+                        || (!AVR_XMEGA
+			    && reload_completed 
                             && cfun->machine->is_signal 
                             && prologue_epilogue_contains (insn)))
                 {
@@ -1715,7 +1759,8 @@ output_movhi (rtx insn, rtx operands[], 
                           AS2 (out,__SP_L__,%A1));
                 }
               /*  In interrupt prolog we know interrupts are enabled.  */
-              else if (reload_completed 
+              else if (!AVR_XMEGA
+			&& reload_completed 
                         && cfun->machine->is_interrupt
                         && prologue_epilogue_contains (insn))
                 {
@@ -1725,12 +1770,25 @@ output_movhi (rtx insn, rtx operands[], 
                            "sei"                   CR_TAB
                            AS2 (out,__SP_L__,%A1));
                 }
-	      *l = 5;
-	      return (AS2 (in,__tmp_reg__,__SREG__)  CR_TAB
-		      "cli"                          CR_TAB
-		      AS2 (out,__SP_H__,%B1)         CR_TAB
-		      AS2 (out,__SREG__,__tmp_reg__) CR_TAB
-		      AS2 (out,__SP_L__,%A1));
+	      if(AVR_XMEGA)
+	        {
+		  *l = 6;
+		  return (AS2 (mov,__tmp_reg__,r24)  CR_TAB
+			  AS2 (ldi,r24,0xD8)         CR_TAB
+			  AS2 (out,__CCP__,r24) CR_TAB
+			  AS2 (out,__SP_H__,%B1)         CR_TAB
+			  AS2 (out,__SP_L__,%A1)         CR_TAB
+			  AS2 (mov,r24,__tmp_reg__));
+		}
+	      else
+	        {
+		  *l = 5;
+		  return (AS2 (in,__tmp_reg__,__SREG__)  CR_TAB
+			  "cli"                          CR_TAB
+			  AS2 (out,__SP_H__,%B1)         CR_TAB
+			  AS2 (out,__SREG__,__tmp_reg__) CR_TAB
+			  AS2 (out,__SP_L__,%A1));
+		}
 	    }
 	  else if (test_hard_reg_class (STACK_REG, src))
 	    {
@@ -1865,7 +1923,7 @@ out_movqi_r_mr (rtx insn, rtx op[], int 
   
   if (CONSTANT_ADDRESS_P (x))
     {
-      if (CONST_INT_P (x) && INTVAL (x) == SREG_ADDR)
+      if (CONST_INT_P (x) && INTVAL (x) == AVR_SREG_ADDR)
 	{
 	  *l = 1;
 	  return AS2 (in,%0,__SREG__);
@@ -1873,7 +1931,8 @@ out_movqi_r_mr (rtx insn, rtx op[], int 
       if (avr_io_address_p (x, 1))
 	{
 	  *l = 1;
-	  return AS2 (in,%0,%1-0x20);
+	  op[2] = GEN_INT(AVR_IO_OFFSET);
+	  return AS2 (in,%0,%1-%2);
 	}
       *l = 2;
       return AS2 (lds,%0,%1);
@@ -2061,8 +2120,9 @@ out_movhi_r_mr (rtx insn, rtx op[], int 
       if (avr_io_address_p (base, 2))
 	{
 	  *l = 2;
-	  return (AS2 (in,%A0,%A1-0x20) CR_TAB
-		  AS2 (in,%B0,%B1-0x20));
+	  op[2] = GEN_INT(AVR_IO_OFFSET);
+	  return (AS2 (in,%A0,%A1-%2) CR_TAB
+		  AS2 (in,%B0,%B1-%2));
 	}
       *l = 4;
       return (AS2 (lds,%A0,%A1) CR_TAB
@@ -2553,7 +2613,7 @@ out_movqi_mr_r (rtx insn, rtx op[], int 
   
   if (CONSTANT_ADDRESS_P (x))
     {
-      if (CONST_INT_P (x) && INTVAL (x) == SREG_ADDR)
+      if (CONST_INT_P (x) && INTVAL (x) == AVR_SREG_ADDR)
 	{
 	  *l = 1;
 	  return AS2 (out,__SREG__,%1);
@@ -2561,7 +2621,8 @@ out_movqi_mr_r (rtx insn, rtx op[], int 
       if (avr_io_address_p (x, 1))
 	{
 	  *l = 1;
-	  return AS2 (out,%0-0x20,%1);
+	  op[2] = GEN_INT(AVR_IO_OFFSET);
+	  return AS2 (out,%0-%2,%1);
 	}
       *l = 2;
       return AS2 (sts,%0,%1);
@@ -2640,11 +2701,20 @@ out_movhi_mr_r (rtx insn, rtx op[], int 
       if (avr_io_address_p (base, 2))
 	{
 	  *l = 2;
-	  return (AS2 (out,%B0-0x20,%B1) CR_TAB
-		  AS2 (out,%A0-0x20,%A1));
+	  op[2] = GEN_INT(AVR_IO_OFFSET);
+          if (AVR_XMEGA)
+	    return (AS2 (out,%A0-%2,%B1) CR_TAB
+		    AS2 (out,%B0-%2,%A1));
+	  else
+	    return (AS2 (out,%B0-%2,%B1) CR_TAB
+		    AS2 (out,%A0-%2,%A1));
 	}
-      return *l = 4, (AS2 (sts,%B0,%B1) CR_TAB
-		      AS2 (sts,%A0,%A1));
+      if (AVR_XMEGA)
+        return *l = 4, (AS2 (sts,%A0,%A1) CR_TAB
+			AS2 (sts,%B0,%B1));
+      else
+        return *l = 4, (AS2 (sts,%B0,%B1) CR_TAB
+			AS2 (sts,%A0,%A1));
     }
   if (reg_base > 0)
     {
@@ -2659,11 +2729,20 @@ out_movhi_mr_r (rtx insn, rtx op[], int 
 			      AS2 (adiw,r26,1)          CR_TAB
 			      AS2 (st,X,__tmp_reg__));
               else
-		return *l=5, (AS2 (mov,__tmp_reg__,r27) CR_TAB
-			      AS2 (adiw,r26,1)          CR_TAB
-			      AS2 (st,X,__tmp_reg__)    CR_TAB
-                              AS2 (sbiw,r26,1)          CR_TAB
-                              AS2 (st,X,r26));
+	        {
+                  if (!AVR_XMEGA)
+		    return *l=5, (AS2 (mov,__tmp_reg__,r27) CR_TAB
+			          AS2 (adiw,r26,1)          CR_TAB
+			          AS2 (st,X,__tmp_reg__)    CR_TAB
+                                  AS2 (sbiw,r26,1)          CR_TAB
+                                  AS2 (st,X,r26));
+		  else
+ 		    return *l=5, (AS2 (mov,__tmp_reg__,r27) CR_TAB
+			          AS2 (st,X,r26)            CR_TAB
+ 			          AS2 (adiw,r26,1)          CR_TAB
+ 			          AS2 (st,X,__tmp_reg__)    CR_TAB
+			          AS2 (sbiw,r26,1));
+		}
             }
           else
             {
@@ -2671,14 +2750,27 @@ out_movhi_mr_r (rtx insn, rtx op[], int 
                 return *l=2, (AS2 (st,X+,%A1) CR_TAB
                               AS2 (st,X,%B1));
               else
-                return *l=3, (AS2 (adiw,r26,1) CR_TAB
-                              AS2 (st,X,%B1)   CR_TAB
-                              AS2 (st,-X,%A1));
+		{
+                  if (!AVR_XMEGA)
+                    return *l=3, (AS2 (adiw,r26,1) CR_TAB
+                                  AS2 (st,X,%B1)   CR_TAB
+                                  AS2 (st,-X,%A1));
+	          else
+                    return *l=3, (AS2 (st,X+,%A1) CR_TAB
+                                  AS2 (st,X,%B1) CR_TAB
+                                  AS2 (sbiw,r26,1));
+		}
             }
         }
       else
-        return  *l=2, (AS2 (std,%0+1,%B1) CR_TAB
-                       AS2 (st,%0,%A1));
+        {
+	  if (!AVR_XMEGA)
+            return  *l=2, (AS2 (std,%0+1,%B1) CR_TAB
+                           AS2 (st,%0,%A1));
+	  else
+            return  *l=2, (AS2 (st,%0,%A1)    CR_TAB
+                           AS2 (std,%0+1,%B1));
+        }
     }
   else if (GET_CODE (base) == PLUS)
     {
@@ -2689,48 +2781,104 @@ out_movhi_mr_r (rtx insn, rtx op[], int 
 	  if (reg_base != REG_Y)
 	    fatal_insn ("incorrect insn:",insn);
 
-	  if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
-	    return *l = 4, (AS2 (adiw,r28,%o0-62) CR_TAB
-			    AS2 (std,Y+63,%B1)    CR_TAB
-			    AS2 (std,Y+62,%A1)    CR_TAB
-			    AS2 (sbiw,r28,%o0-62));
-
-	  return *l = 6, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
-			  AS2 (sbci,r29,hi8(-%o0)) CR_TAB
-			  AS2 (std,Y+1,%B1)        CR_TAB
-			  AS2 (st,Y,%A1)           CR_TAB
-			  AS2 (subi,r28,lo8(%o0))  CR_TAB
-			  AS2 (sbci,r29,hi8(%o0)));
+          if (!AVR_XMEGA)
+            {
+	      if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
+	        return *l = 4, (AS2 (adiw,r28,%o0-62) CR_TAB
+			        AS2 (std,Y+63,%B1)    CR_TAB
+			        AS2 (std,Y+62,%A1)    CR_TAB
+			        AS2 (sbiw,r28,%o0-62));
+
+	      return *l = 6, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
+			      AS2 (sbci,r29,hi8(-%o0)) CR_TAB
+			      AS2 (std,Y+1,%B1)        CR_TAB
+			      AS2 (st,Y,%A1)           CR_TAB
+			      AS2 (subi,r28,lo8(%o0))  CR_TAB
+			      AS2 (sbci,r29,hi8(%o0)));
+            }
+	  else
+	    {
+ 	      if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
+ 	        return *l = 4, (AS2 (adiw,r28,%o0-62) CR_TAB
+			        AS2 (std,Y+62,%A1)    CR_TAB
+ 			        AS2 (std,Y+63,%B1)    CR_TAB
+ 			        AS2 (sbiw,r28,%o0-62));
+ 
+ 	      return *l = 6, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
+ 			      AS2 (sbci,r29,hi8(-%o0)) CR_TAB
+			      AS2 (st,Y,%A1)           CR_TAB
+ 			      AS2 (std,Y+1,%B1)        CR_TAB
+ 			      AS2 (subi,r28,lo8(%o0))  CR_TAB
+ 			      AS2 (sbci,r29,hi8(%o0)));
+ 	    }
 	}
       if (reg_base == REG_X)
 	{
 	  /* (X + d) = R */
 	  if (reg_src == REG_X)
             {
-	      *l = 7;
-	      return (AS2 (mov,__tmp_reg__,r26)  CR_TAB
-		      AS2 (mov,__zero_reg__,r27) CR_TAB
-                      AS2 (adiw,r26,%o0+1)       CR_TAB
-		      AS2 (st,X,__zero_reg__)    CR_TAB
-		      AS2 (st,-X,__tmp_reg__)    CR_TAB
-		      AS1 (clr,__zero_reg__)     CR_TAB
+	      if (!AVR_XMEGA)
+	        {
+	          *l = 7; 
+	          return (AS2 (mov,__tmp_reg__,r26)  CR_TAB
+		          AS2 (mov,__zero_reg__,r27) CR_TAB
+                          AS2 (adiw,r26,%o0+1)       CR_TAB
+		          AS2 (st,X,__zero_reg__)    CR_TAB
+		          AS2 (st,-X,__tmp_reg__)    CR_TAB
+		          AS1 (clr,__zero_reg__)     CR_TAB
+                          AS2 (sbiw,r26,%o0));
+		}
+	      else
+	        {
+ 	          *l = 7;
+ 	          return (AS2 (mov,__tmp_reg__,r26)  CR_TAB
+ 		          AS2 (mov,__zero_reg__,r27) CR_TAB
+		          AS2 (adiw,r26,%o0)         CR_TAB
+		          AS2 (st,X+,__tmp_reg__)    CR_TAB
+ 		          AS2 (st,X,__zero_reg__)    CR_TAB
+ 		          AS1 (clr,__zero_reg__)     CR_TAB
+		          AS2 (sbiw,r26,%o0+1));
+	        }
+	    }
+	  if (!AVR_XMEGA)
+            {	    
+	      *l = 4;
+              return (AS2 (adiw,r26,%o0+1) CR_TAB
+                      AS2 (st,X,%B1)       CR_TAB
+                      AS2 (st,-X,%A1)      CR_TAB
                       AS2 (sbiw,r26,%o0));
 	    }
-	  *l = 4;
-          return (AS2 (adiw,r26,%o0+1) CR_TAB
-                  AS2 (st,X,%B1)       CR_TAB
-                  AS2 (st,-X,%A1)      CR_TAB
-                  AS2 (sbiw,r26,%o0));
+	  else
+	    {
+ 	      *l = 4;
+	      return (AS2 (adiw,r26,%o0) CR_TAB
+		      AS2 (st,X+,%A1)    CR_TAB
+		      AS2 (st,X,%B1)     CR_TAB
+		      AS2 (sbiw,r26,%o0+1));
+            }
 	}
-      return *l=2, (AS2 (std,%B0,%B1)    CR_TAB
-                    AS2 (std,%A0,%A1));
+	
+      if (!AVR_XMEGA)
+        return *l=2, (AS2 (std,%B0,%B1)    CR_TAB
+                      AS2 (std,%A0,%A1));
+      else
+        return *l=2, (AS2 (std,%A0,%A1)    CR_TAB
+	              AS2 (std,%B0,%B1));
     }
   else if (GET_CODE (base) == PRE_DEC) /* (--R) */
-    return *l=2, (AS2 (st,%0,%B1) CR_TAB
-		  AS2 (st,%0,%A1));
+    {
+      if (mem_volatile_p && AVR_XMEGA)
+        return *l = 4, (AS2 (sbiw,%r0,1)    CR_TAB 
+                        AS2 (st,%p0+,%A1)   CR_TAB
+                        AS2 (st,%p0,%B1)    CR_TAB
+                        AS2 (sbiw,%r0,2));
+      else
+        return *l=2, (AS2 (st,%0,%B1) CR_TAB
+		      AS2 (st,%0,%A1));
+    }
   else if (GET_CODE (base) == POST_INC) /* (R++) */
     {
-      if (mem_volatile_p)
+      if (mem_volatile_p && !AVR_XMEGA)
         {
           if (REGNO (XEXP (base, 0)) == REG_X)
             {
@@ -2751,7 +2899,7 @@ out_movhi_mr_r (rtx insn, rtx op[], int 
 
       *l = 2;
       return (AS2 (st,%0,%A1)  CR_TAB
-            AS2 (st,%0,%B1));
+              AS2 (st,%0,%B1));
     }
   fatal_insn ("unknown move insn:",insn);
   return "";
@@ -4631,6 +4779,7 @@ const struct attribute_spec avr_attribut
   { "progmem",   0, 0, false, false, false,  avr_handle_progmem_attribute },
   { "signal",    0, 0, true,  false, false,  avr_handle_fndecl_attribute },
   { "interrupt", 0, 0, true,  false, false,  avr_handle_fndecl_attribute },
+  { "nmi",       0, 0, true,  false, false,  avr_handle_fndecl_attribute },
   { "naked",     0, 0, false, true,  true,   avr_handle_fntype_attribute },
   { "OS_task",   0, 0, false, true,  true,   avr_handle_fntype_attribute },
   { NULL,        0, 0, false, false, false, NULL }
@@ -4719,6 +4868,14 @@ avr_handle_fndecl_attribute (tree *node,
                        func_name);
             }
         }
+      else if (strncmp (attr, "nmi", strlen ("nmi")) == 0)
+        {
+          if (strncmp (func_name, "__vector", strlen ("__vector")) != 0)
+            {
+              warning (0, "%qs appears to be a misspelled nmi handler",
+                       func_name);
+            }
+        }
     }
 
   return NULL_TREE;
@@ -4844,7 +5001,8 @@ avr_file_start (void)
 /*  fprintf (asm_out_file, "\t.arch %s\n", avr_mcu_name);*/
   fputs ("__SREG__ = 0x3f\n"
 	 "__SP_H__ = 0x3e\n"
-	 "__SP_L__ = 0x3d\n", asm_out_file);
+	 "__SP_L__ = 0x3d\n"
+	 "__CCP__  = 0x34\n", asm_out_file);
   
   fputs ("__tmp_reg__ = 0\n" 
          "__zero_reg__ = 1\n", asm_out_file);
@@ -5708,15 +5866,18 @@ avr_hard_regno_mode_ok (int regno, enum 
   return !(regno & 1);
 }
 
-/* Returns 1 if X is a valid address for an I/O register of size SIZE
-   (1 or 2).  Used for lds/sts -> in/out optimization.  Add 0x20 to SIZE
-   to check for the lower half of I/O space (for cbi/sbi/sbic/sbis).  */
+/* Returns 1 if X is a valid address for an I/O register of size SIZE 
+   (1 or 2).  Used for lds/sts -> in/out optimization.  */
 
 int
 avr_io_address_p (rtx x, int size)
 {
-  return (optimize > 0 && GET_CODE (x) == CONST_INT
-	  && INTVAL (x) >= 0x20 && INTVAL (x) <= 0x60 - size);
+  if(AVR_XMEGA)
+    return (optimize > 0 && GET_CODE (x) == CONST_INT
+	    && INTVAL (x) >= 0 && INTVAL (x) <= 0x40 - size);
+  else
+    return (optimize > 0 && GET_CODE (x) == CONST_INT
+	    && INTVAL (x) >= 0x20 && INTVAL (x) <= 0x60 - size);
 }
 
 const char *
@@ -5877,16 +6038,17 @@ avr_out_sbxx_branch (rtx insn, rtx opera
 
   if (GET_CODE (operands[1]) == CONST_INT)
     {
-      if (INTVAL (operands[1]) < 0x40)
+      operands[4] = GEN_INT(AVR_IO_OFFSET); /* operands[3] is for the jump */
+      if (low_io_address_operand (operands[1], VOIDmode))
 	{
 	  if (comp == EQ)
-	    output_asm_insn (AS2 (sbis,%1-0x20,%2), operands);
+	    output_asm_insn (AS2 (sbis,%1-%4,%2), operands);
 	  else
-	    output_asm_insn (AS2 (sbic,%1-0x20,%2), operands);
+	    output_asm_insn (AS2 (sbic,%1-%4,%2), operands);
 	}
       else
 	{
-	  output_asm_insn (AS2 (in,__tmp_reg__,%1-0x20), operands);
+	  output_asm_insn (AS2 (in,__tmp_reg__,%1-%4), operands);
 	  if (comp == EQ)
 	    output_asm_insn (AS2 (sbrs,__tmp_reg__,%2), operands);
 	  else
--- gcc/config/avr/avr.h.orig	2008-06-08 10:24:28.186941800 -0600
+++ gcc/config/avr/avr.h	2008-06-08 10:28:40.274905800 -0600
@@ -44,8 +44,11 @@ struct base_arch_s {
   /* Core have 'EICALL' and 'EIJMP' instructions.  */
   int have_eijmp_eicall;
 
-  /* Reserved. */
-  int reserved;
+  /* Core is in Xmega family.  */
+  int xmega;
+
+  /* Core have RAMPX, RAMPY and RAMPD registers.  */
+  int have_rampx_y_d;
   
   const char *const macro;
 };
@@ -68,6 +71,13 @@ extern const struct base_arch_s *avr_cur
 	builtin_define ("__AVR_HAVE_ELPMX__");	\
       if (avr_have_movw_lpmx_p)			\
 	builtin_define ("__AVR_HAVE_MOVW__");	\
+      if (avr_current_arch->have_elpm)		\
+        {					\
+	  builtin_define ("__AVR_HAVE_RAMPZ__");\
+	  builtin_define ("__AVR_HAVE_ELPM__");	\
+	}					\
+      if (avr_current_arch->have_elpmx)		\
+	builtin_define ("__AVR_HAVE_ELPMX__");	\
       if (avr_have_movw_lpmx_p)			\
 	builtin_define ("__AVR_HAVE_LPMX__");	\
       if (avr_asm_only_p)			\
@@ -88,6 +98,17 @@ extern const struct base_arch_s *avr_cur
 	builtin_define ("__AVR_HAVE_EIJMP_EICALL__"); \
       if (TARGET_NO_INTERRUPTS)			\
 	builtin_define ("__NO_INTERRUPTS__");	\
+      if (avr_current_arch->xmega)              \
+	{					\
+	  builtin_define ("__AVR_XMEGA__");     \
+	  builtin_define ("__AVR_HAVE_SPMX__"); \
+	}					\
+      if (avr_current_arch->have_rampx_y_d)     \
+	{					\
+	  builtin_define ("__AVR_HAVE_RAMPX__");\
+	  builtin_define ("__AVR_HAVE_RAMPY__");\
+	  builtin_define ("__AVR_HAVE_RAMPD__");\
+	}					\
     }						\
   while (0)
 
@@ -107,10 +128,15 @@ extern GTY(()) section *progmem_section;
 #define AVR_HAVE_LPMX (avr_have_movw_lpmx_p)
 #define AVR_HAVE_RAMPZ (avr_current_arch->have_elpm)
 #define AVR_HAVE_EIJMP_EICALL (avr_current_arch->have_eijmp_eicall)
+#define AVR_XMEGA (avr_current_arch->xmega)
 
 #define AVR_2_BYTE_PC (!AVR_HAVE_EIJMP_EICALL)
 #define AVR_3_BYTE_PC (AVR_HAVE_EIJMP_EICALL)
 
+#define AVR_IO_OFFSET (AVR_XMEGA ? 0 : 0x20)
+#define AVR_RAMPZ_ADDR (AVR_XMEGA ? 0x3B : 0x5B)
+#define AVR_SREG_ADDR (AVR_XMEGA ? 0x3F: 0x5F)
+
 #define TARGET_VERSION fprintf (stderr, " (GNU assembler syntax)");
 
 #define OVERRIDE_OPTIONS avr_override_options ()
@@ -849,6 +875,8 @@ mmcu=*:-mmcu=%*}"
   mmcu=at90usb128*|\
   mmcu=at94k: -m avr5}\
 %{mmcu=atmega256*:-m avr6}\
+%{mmcu=atxmega64a1:-m avrxmega5} \
+%{mmcu=atxmega128a1:-m avrxmega7} \
 %{mmcu=atmega324*|\
   mmcu=atmega325*|\
   mmcu=atmega328p|\
@@ -994,7 +1022,9 @@ mmcu=*:-mmcu=%*}"
 %{mmcu=atmega2561:crtm2561.o%s} \
 %{mmcu=at90can128:crtcan128.o%s} \
 %{mmcu=at90usb1286:crtusb1286.o%s} \
-%{mmcu=at90usb1287:crtusb1287.o%s}"
+%{mmcu=at90usb1287:crtusb1287.o%s} \
+%{mmcu=atxmega5|mmcu=atxmega64a1:crtx64a1.o%s} \
+%{mmcu=atxmega7|mmcu=atxmega128a1:crtx128a1.o%s}"
 
 #define EXTRA_SPECS {"crt_binutils", CRT_BINUTILS_SPECS},
 
@@ -1050,8 +1080,12 @@ struct machine_function GTY(())
   /* 'true' - if current function is a signal function 
      as specified by the "signal" attribute.  */
   int is_signal;
-  
+
   /* 'true' - if current function is a signal function 
+     as specified by the "nmi" attribute.  */
+  int is_nmi;
+  
+  /* 'true' - if current function is a task function 
      as specified by the "OS_task" attribute.  */
   int is_OS_task;
 };
--- gcc/config/avr/avr.md.orig	2008-06-08 10:24:28.171355800 -0600
+++ gcc/config/avr/avr.md	2008-06-08 10:29:58.610141800 -0600
@@ -47,9 +47,6 @@
    (TMP_REGNO	0)	; temporary register r0
    (ZERO_REGNO	1)	; zero register r1
    
-   (SREG_ADDR   0x5F)
-   (RAMPZ_ADDR  0x5B)
-   
    (UNSPEC_STRLEN	0)
    (UNSPEC_INDEX_JMP	1)
    (UNSPEC_SEI		2)
@@ -2681,7 +2678,8 @@
   "(optimize > 0)"
 {
   operands[2] = GEN_INT (exact_log2 (~INTVAL (operands[1]) & 0xff));
-  return AS2 (cbi,%0-0x20,%2);
+  operands[3] = GEN_INT(AVR_IO_OFFSET);
+  return AS2 (cbi,%0-%3,%2);
 }
   [(set_attr "length" "1")
    (set_attr "cc" "none")])
@@ -2693,7 +2691,8 @@
   "(optimize > 0)"
 {
   operands[2] = GEN_INT (exact_log2 (INTVAL (operands[1]) & 0xff));
-  return AS2 (sbi,%0-0x20,%2);
+  operands[3] = GEN_INT(AVR_IO_OFFSET);
+  return AS2 (sbi,%0-%3,%2);
 }
   [(set_attr "length" "1")
    (set_attr "cc" "none")])
Index: gcc/config/avr/predicates.md
===================================================================
--- gcc/config/avr/predicates.md	(revision 132445)
+++ gcc/config/avr/predicates.md	(working copy)
@@ -45,12 +45,16 @@
 ;; Return true if OP is a valid address for lower half of I/O space.
 (define_predicate "low_io_address_operand"
   (and (match_code "const_int")
-       (match_test "IN_RANGE((INTVAL (op)), 0x20, 0x3F)")))
+       (if_then_else (match_test "AVR_XMEGA") 
+                     (match_test "IN_RANGE((INTVAL (op)), 0x00, 0x1F)")
+	             (match_test "IN_RANGE((INTVAL (op)), 0x20, 0x3F)"))))
 
 ;; Return true if OP is a valid address for high half of I/O space.
 (define_predicate "high_io_address_operand"
   (and (match_code "const_int")
-       (match_test "IN_RANGE((INTVAL (op)), 0x40, 0x5F)")))
+       (if_then_else (match_test "AVR_XMEGA") 
+                     (match_test "IN_RANGE((INTVAL (op)), 0x20, 0x3F)")
+	             (match_test "IN_RANGE((INTVAL (op)), 0x40, 0x5F)"))))
 
 ;; Return 1 if OP is the zero constant for MODE.
 (define_predicate "const0_operand"
--- gcc/config/avr/t-avr.orig	2008-02-19 17:25:31.546827500 -0700
+++ gcc/config/avr/t-avr	2008-02-20 09:22:51.709554900 -0700
@@ -37,8 +37,8 @@ fp-bit.c: $(srcdir)/config/fp-bit.c $(sr
 
 FPBIT = fp-bit.c
 
-MULTILIB_OPTIONS = mmcu=avr2/mmcu=avr25/mmcu=avr3/mmcu=avr31/mmcu=avr35/mmcu=avr4/mmcu=avr5/mmcu=avr51/mmcu=avr6
-MULTILIB_DIRNAMES = avr2 avr25 avr3 avr31 avr35 avr4 avr5 avr51 avr6
+MULTILIB_OPTIONS = mmcu=avr2/mmcu=avr25/mmcu=avr3/mmcu=avr31/mmcu=avr35/mmcu=avr4/mmcu=avr5/mmcu=avr51/mmcu=avr6/mmcu=avrxmega5/mmcu=avrxmega7
+MULTILIB_DIRNAMES = avr2 avr25 avr3 avr31 avr35 avr4 avr5 avr51 avr6 avrxmega5 avrxmega7
 
 # The many avr2 matches are not listed here - this is the default.
 MULTILIB_MATCHES = \
@@ -125,7 +125,9 @@ MULTILIB_MATCHES = \
 	mmcu?avr51=mmcu?at90usb1286 \
 	mmcu?avr51=mmcu?at90usb1287 \
  	mmcu?avr6=mmcu?atmega2560 \
- 	mmcu?avr6=mmcu?atmega2561
+ 	mmcu?avr6=mmcu?atmega2561 \
+ 	mmcu?avrxmega5=mmcu?atxmega64a1 \
+ 	mmcu?avrxmega7=mmcu?atxmega128a1
 
 MULTILIB_EXCEPTIONS =
 
